Operating systems, especially those directed to personal computers, have made substantial sophisticated and technological advances in a relatively short period of time. These advances have corresponded to advances in computer processing technology, such as hardware process switching, multi-tasking, multi-threading, and the like. Whereas on generations of personal computers their operating system supported one user process in which a user could execute one program at a time, in current operating systems, multiple programs and processes execute simultaneously or, at least, in an apparently simultaneous manner, taking advantage of the abilities of the hardware as well as advanced programming techniques.
As those skilled in the art will appreciate, in order to manage the execution of programs or modules on a computer, each program executes with a predefined structure, imposed by the operating system, which is referred to hereafter as a process. Of course, each operating system designed is free to name its structures as desired. As such, some operating systems refer to their structures as tasks, while others may have yet other names. Thus, for the sake of clarity, the term process defines the fundamental structure used by an operating system to execute a software module. A process contains the resources (e.g., memory, register values, stack space, temporary disk space, communication channels, and the like) that are requested by an application and allocated to it by the operating system. Thus, in a multi-processing (or multi-tasking) operating system, multiple programs or modules may be running simultaneously.
Another advance in operating system technology (which generally also corresponds to advances in computer hardware technology), is the use of threads. As is well known in the art, programs are now written such that multiple aspects of the program may be executing simultaneously. This is especially true, though not the exclusive domain, of programs structured and written to take advantage of numerous object-oriented programming functionalities. Unlike a process, a thread represents a unit of execution for a given process. Generally speaking, while a process represents a “job” that an operating system performs, a thread represents one of a potentially many sub-tasks necessary to complete the job. Moreover, when a process is created, it is created with a main thread. Subsequently, that main thread may create other threads for multiplexing various sub-tasks.
The thread construct is very lightweight with regard to system resources. It has an execution context, but very little else. This is in contrast to the process, which is allocated all of the resources necessary to execute the program, as well as the resources requested by the program. The thread, being a unit of execution of a process, has access to the resources allocated to the process. There is a one to many relationship between processes and threads: each process has one or more threads or execution points.
As is well known in the art, operating systems provide a wide array of services to a user. These services include broad categories such as, but not limited to, file I/O, communication and/or networking services, graphics display services, timers, peripheral interfaces, and the like. Indeed, a quick check of processes and threads executing on an “idle” computer system, i.e., one in which the user has not executed any application, reveals that the computer system, in fact, is running many processes. Many services, including operating system services, are running even on an “idle” computer.
Generally, operating system developers are keenly aware that processes take up more system resources than do threads. They are further aware that if they are to provide a process for each service that must execute on an operational system, the amount of resources that would be required is staggering. Moreover, there would be significant performance issues due to the overhead of scheduling a process corresponding to each service. To compensate, at least some operating system providers group various operating system services into a single process. These processes have multiple entry points, each entry point corresponding to a service provided by the operating system which will be executed by a thread. In this manner, the operating system provider can continue to offer its wide variety of services to other applications operating on the computer system without incurring substantial resource or performance overhead for each service available. Microsoft Corporation's Windows family of operating systems, such as Windows XP, combines multiple operating system services into a single process, where each service is executed by one or more threads associated with the process.
When instantiating a process, the operating system will allocate the resources necessary for the corresponding program to run, and also load at least a portion of the program into memory. However, the entire program need not be loaded, especially when the program is large and is broken into various modules or libraries. When code in those libraries is needed, a fault is generated which causes them to be loaded into memory, and then execution continues. Operating system services are frequently implemented such that if they are requested, the code corresponding to that service is loaded into the process and a thread begins execution at the requested entry point.
One aspect of processes is that the operating system assigns each process a unique identifier. These process identifiers (PIDs) are useful for a variety of reasons, and especially when tracking/tracing the execution of the processes on the computer system. Tracking or tracing processes executing on the computer system are frequently performed to identify bottlenecks in the computer system, perform system modeling, identify which processes are performing which actions (such as identifying a rogue process that opens unsecured ports on the computer), and the like.
Operating system services are the frequent target of malware—malicious software whose intent is to corrupt, destroy, perform identity theft, or otherwise harm the computer or the computer user. Malware includes Trojan horses, worms, bots, and viruses that individually or collectively subject a computer or computer network to various types of attacks, both internal and external, resulting in data and identity thefts, loss of data, denial of service attacks, and the like. Quite often it is the object of malware to first corrupt one or more operating system services on a computer system. Once a service is corrupted, a request is made to the corrupt service which is then loaded into an executing process and a thread begins execution of that service. Once executing, the computer system is compromised, vulnerable to the malware's ill intent.
One novel way to ensure that operating system components are not corrupted, or, if they do become corrupted, that the operating system components are prevented from further compromising the computer system, is to ensure that an operating system component executes within prescribed bounds. This is sometimes referred to as “hardening” the operating system component, and may be applied to non-operating system components as well. When a hardened operating system component executes instructions outside of its prescribed bounds, it is viewed as a rogue, or corrupted, operating system component and any activity it performs that falls outside of those prescribed bounds is blocked, or alternatively, an alert is generated to an administrator prompting an inquiry into its behaviors.
Component hardening relies on the ability to identify the component, and relate the identified component to a set of rules specifying what is allowable and/or what is not allowable. More particularly, component hardening relies upon one or more unique security identifiers assigned to a component being identified as being responsible for operations conduction by the component. It is through these security identifiers that an operating system can relate the identified component to its particular set of rules. Unfortunately, currently, identification of an individual service conducting an operation in a process with multiple services is not possible. Thus, service hardening is currently based on an aggregated set of security rules associated with each service in the process. Of course, this means that the least restrictive set of rules is used to harden all of the services in a process.
Clearly, each operating system service, if it is to be hardened, will have its own set of activities identifying what it can and cannot do. A process may contain operating system services with similar or vastly different prescribed behaviors. Though an effort could be made to group operating system services with similar behavioral rules into a process, there will still likely be differences. Conversely, for various reasons, it may be necessary to group operating system services having vastly divergent behavioral rules into a single process, such as when a system is constrained by memory or CPU processing power issues, such as found with small form-factor devices, or when the system is hosting multiple services as a multi-functional server. As the only current way to identify executing code to a set of rules is through a security identifier associated with a process, and as multiple operating system services (potentially having vastly different rules) are collected into a single process, it is difficult or impossible to determine which operating system service (of many that may be assigned to a given process) is executing. The implications are that an individual service's hardening can not be enforced when it shares the process space with other services. Since only the process can be identified as taking action, the hardening rules for the services aggregated into the process must be less restrictive than they would be if each individual operating system service were placed in its own process. Put another way, to harden an operating system process containing multiple operating system services, the process must currently adopt a single set of hardening rules. Moreover, this single set of hardening rules is a combination of the least restrictive rules of the services. Unfortunately, this means that some operating system services in a process are given more “privileges” than they would normally be allowed. As such, their corruption still poses a significant threat to the computer system, even when the process is “hardened.”